package com.sdses.weather.utils;

import cn.hutool.core.util.StrUtil;
import com.sdses.weather.config.WeatherProviderSchemaConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 排序辅助类：支持对 String 类型字段按指定类型（int/double/date 等）进行排序
 * 适用于字段存储为 String，但需按数值/时间等逻辑排序的场景
 */
public class SortHelper {

    private static final Logger log = LoggerFactory.getLogger(SortHelper.class);

    /**
     * 对列表按字段配置进行排序
     *
     * @param list   待排序列表
     * @param fields 字段映射配置（含 sortType/sortFormat）
     * @param <T>    列表元素类型
     * @return 排序后的新列表
     */
    public static <T> List<T> sortByConfig(List<T> list, List<WeatherProviderSchemaConfig.FieldMapping> fields) {
        if (list == null || list.isEmpty()) {
            return list;
        }

        List<WeatherProviderSchemaConfig.FieldMapping> sortFields = fields.stream()
                .filter(f -> f.getSortType() != null && !f.getSortType().trim().isEmpty())
                .collect(Collectors.toList());

        if (sortFields.isEmpty()) {
            return list;
        }

        Comparator<T> comparator = null;
        for (WeatherProviderSchemaConfig.FieldMapping field : sortFields) {
            Comparator<T> comp = createFieldComparator(field);
            if (comp != null) {
                comparator = (comparator == null) ? comp : comparator.thenComparing(comp);
            }
        }

        if (comparator == null) {
            return list;
        }

        return list.stream()
                .sorted(comparator)
                .collect(Collectors.toList());
    }

    /**
     * 根据字段配置创建对应的比较器
     */
    private static <T> Comparator<T> createFieldComparator(WeatherProviderSchemaConfig.FieldMapping field) {
        String fieldName = StrUtil.isEmpty(field.getJava()) ? field.getJson() : field.getJava();
        String sortType = (field.getSortType() != null ? field.getSortType() : "string").toLowerCase().trim();

        return (o1, o2) -> {
            String v1 = null, v2 = null;
            try {
                v1 = getStringValue(o1, fieldName);
                v2 = getStringValue(o2, fieldName);

                boolean isV1Empty = isEmpty(v1);
                boolean isV2Empty = isEmpty(v2);
                if (isV1Empty && isV2Empty) return 0;
                if (isV1Empty) return 1;
                if (isV2Empty) return -1;

                if ("int".equals(sortType)) {
                    return Integer.compare(Integer.parseInt(v1.trim()), Integer.parseInt(v2.trim()));
                } else if ("long".equals(sortType)) {
                    return Long.compare(Long.parseLong(v1.trim()), Long.parseLong(v2.trim()));
                } else if ("double".equals(sortType)) {
                    return Double.compare(Double.parseDouble(v1.trim()), Double.parseDouble(v2.trim()));
                } else if ("date".equals(sortType)) {
                    return parseDate(v1, field.getSortFormat()).compareTo(parseDate(v2, field.getSortFormat()));
                } else if ("localdatetime".equals(sortType)) {
                    return parseLocalDateTime(v1, field.getSortFormat()).compareTo(parseLocalDateTime(v2, field.getSortFormat()));
                } else {
                    return v1.compareTo(v2); // string 默认
                }
            } catch (Exception e) {
                log.warn("Sort failed for field '{}', values: '{}', '{}', error: {}",
                        fieldName,
                        getStringValueQuietly(o1, fieldName),
                        getStringValueQuietly(o2, fieldName),
                        e.getMessage(), e);

                String s1 = v1 != null ? v1 : "";
                String s2 = v2 != null ? v2 : "";
                return s1.compareTo(s2);
            }
        };
    }

    private static String getStringValue(Object obj, String fieldName) {
        try {
            Field f = obj.getClass().getDeclaredField(fieldName);
            f.setAccessible(true);
            Object val = f.get(obj);
            return val == null ? null : val.toString();
        } catch (Exception e) {
            log.warn("Cannot access field: {}.{}", obj.getClass().getSimpleName(), fieldName);
            return null;
        }
    }

    private static String getStringValueQuietly(Object obj, String fieldName) {
        try {
            Field f = obj.getClass().getDeclaredField(fieldName);
            f.setAccessible(true);
            return Objects.toString(f.get(obj), null);
        } catch (Exception e) {
            return "?";
        }
    }

    private static boolean isEmpty(String s) {
        return s == null || s.trim().isEmpty();
    }


    private static Date parseDate(String s, String format) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(
                format != null && !format.isEmpty() ? format : "yyyy-MM-dd HH:mm:ss"
        );
        return sdf.parse(s.trim());
    }

    private static LocalDateTime parseLocalDateTime(String s, String format) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
                format != null && !format.isEmpty() ? format : "yyyy-MM-dd HH:mm:ss"
        );
        return LocalDateTime.parse(s.trim(), dtf);
    }
}